/*
 * Tulalip Library, an enhanced ORMLite library.
 * Copyright (C) 2010 Richard Schilling
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.gnu.tulalip.android.widget;

import java.util.List;

import android.widget.BaseAdapter;

import com.j256.ormlite.dao.RuntimeExceptionDao;
import com.j256.ormlite.stmt.PreparedQuery;

/**
 * An adapter that works on lists of objects. Data is not cached in memory. Each
 * function call usually results in a database operation.
 * Use ORMAdapterCache to use more memory but have shorter runtimes.
 * 
 * @param <T> the ORMLite defined class
 * @param <ID> the type of <T> identifier field.
 * @author Richard Schilling (coderroadie@gmail.com)
 */
public abstract class ORMAdapter<T extends AdapterObject<T>, ID> extends BaseAdapter {

    /**
     * DAO that is used to retrieve data.
     */
    protected final RuntimeExceptionDao<T, ID> dao;

    /**
     * The query used to retrieve objects from the database.
     */
    protected final PreparedQuery<T> query;

    /**
     * A new adapter.
     * 
     * @param helper the helper that is used to get objects of type {@code <T>}
     *            from.
     */
    public ORMAdapter(RuntimeExceptionDao<T, ID> dao, PreparedQuery<T> query) {
        this.dao = dao;
        this.query = query;
    }

    /**
     * Returns object in the specified position (zero based). The position is
     * based on the sorted list returned by {@link #getList getList}.
     * 
     * @return the item of class {@code <T>} in the specified position
     */
    @Override
    public Object getItem(int position) {
        List<T> data = getList();
        return data.get(position);
    }

    /**
     * Adds an item to the underlying data store, and then notifies all lists
     * that the data has changed.
     * 
     * @param newItem
     */
    public void addItem(T newItem) {
        dao.create(newItem);
        notifyDataSetChanged();
    }

    /**
     * Deletes the item from the underlying database and refreshes the adapter.
     * 
     * @param item the item to delete.
     */
    public void deleteItem(T item) {
        dao.delete(item);
        notifyDataSetChanged();
    }

    /**
     * Updates the specified item in the underlying database.
     * 
     * @param item the item to update.
     */
    public void updateItem(T item) {
        dao.update(item);
        notifyDataSetChanged();
    }

    /**
     * Returns the identifier of the item in the specified position
     * 
     * @param the position to return the id for
     * @retrun the position's identifier
     */
    @Override
    public long getItemId(int position) {
        return ((AdapterObject<T>) getList().get(position)).getId();
    }

    /**
     * Returns the position in the underlying adapter's list of the item that
     * contains the specified id. If the ID is not found an exception is thrown.
     * 
     * @param id the id to look for.
     * @return the position of the item with the specified id.
     * @throws IllegalArgumentException if an item with the id is not present in
     *             the list.
     */
    public int getPositionFromId(long id) {
        List<T> list = getList();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getId() == id)
                return i;
        }

        throw new IllegalArgumentException("item with id not found");
    }

    /**
     * Returns the list of all items of type {@code <T>} in the database. The
     * listi so sorted in memory before being returned.
     * 
     * @return the list of all items in the database.
     */
    public abstract List<T> getList();

    /**
     * Returns the number of items of type {@code <T>} in the database.
     * 
     * @return object count.
     */
    @Override
    public abstract int getCount();

    /**
     * Refreshes the in-memory data set.
     */
    public abstract void refresh();

}
